<!DOCTYPE html><html lang="zh-CN" data-theme="light"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"><title>Spring入门 | 梓琰苑</title><meta name="keywords" content="Spring"><meta name="author" content="Milk Yang"><meta name="copyright" content="Milk Yang"><meta name="format-detection" content="telephone=no"><meta name="theme-color" content="#ffffff"><meta name="description" content="[TOC] Spring入门使用Spring容器Spring有两个核心接口，BeanFactory和ApplicationContext,其中ApplicationContext是BeanFactory的子接口。它们都可代表Spring容器，Spring容器是生成Bean实例的工厂，并管理容器中的Bean. Spring容器BeanFactory是Spring最基本的容器，包含如下几个基本方法：">
<meta property="og:type" content="article">
<meta property="og:title" content="Spring入门">
<meta property="og:url" content="http://yzb317415.gitee.io/blog/2022/06/22/Spring%E5%85%A5%E9%97%A8/index.html">
<meta property="og:site_name" content="梓琰苑">
<meta property="og:description" content="[TOC] Spring入门使用Spring容器Spring有两个核心接口，BeanFactory和ApplicationContext,其中ApplicationContext是BeanFactory的子接口。它们都可代表Spring容器，Spring容器是生成Bean实例的工厂，并管理容器中的Bean. Spring容器BeanFactory是Spring最基本的容器，包含如下几个基本方法：">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="">
<meta property="article:published_time" content="2022-06-22T10:06:45.824Z">
<meta property="article:modified_time" content="2018-11-05T09:28:01.000Z">
<meta property="article:author" content="Milk Yang">
<meta property="article:tag" content="Spring">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content=""><link rel="shortcut icon" href="/blog/img/favicon.png"><link rel="canonical" href="http://yzb317415.gitee.io/blog/2022/06/22/Spring%E5%85%A5%E9%97%A8/"><link rel="preconnect" href="//cdn.jsdelivr.net"/><link rel="preconnect" href="//busuanzi.ibruce.info"/><link rel="stylesheet" href="/blog/css/index.css"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@6/css/all.min.css" media="print" onload="this.media='all'"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fancyapps/ui/dist/fancybox.css" media="print" onload="this.media='all'"><script>const GLOBAL_CONFIG = { 
  root: '/blog/',
  algolia: undefined,
  localSearch: undefined,
  translate: undefined,
  noticeOutdate: undefined,
  highlight: {"plugin":"highlighjs","highlightCopy":true,"highlightLang":true,"highlightHeightLimit":false},
  copy: {
    success: '复制成功',
    error: '复制错误',
    noSupport: '浏览器不支持'
  },
  relativeDate: {
    homepage: false,
    post: false
  },
  runtime: '',
  date_suffix: {
    just: '刚刚',
    min: '分钟前',
    hour: '小时前',
    day: '天前',
    month: '个月前'
  },
  copyright: undefined,
  lightbox: 'fancybox',
  Snackbar: undefined,
  source: {
    justifiedGallery: {
      js: 'https://cdn.jsdelivr.net/npm/flickr-justified-gallery@2/dist/fjGallery.min.js',
      css: 'https://cdn.jsdelivr.net/npm/flickr-justified-gallery@2/dist/fjGallery.min.css'
    }
  },
  isPhotoFigcaption: false,
  islazyload: false,
  isAnchor: false
}</script><script id="config-diff">var GLOBAL_CONFIG_SITE = {
  title: 'Spring入门',
  isPost: true,
  isHome: false,
  isHighlightShrink: false,
  isToc: true,
  postUpdate: '2018-11-05 17:28:01'
}</script><noscript><style type="text/css">
  #nav {
    opacity: 1
  }
  .justified-gallery img {
    opacity: 1
  }

  #recent-posts time,
  #post-meta time {
    display: inline !important
  }
</style></noscript><script>(win=>{
    win.saveToLocal = {
      set: function setWithExpiry(key, value, ttl) {
        if (ttl === 0) return
        const now = new Date()
        const expiryDay = ttl * 86400000
        const item = {
          value: value,
          expiry: now.getTime() + expiryDay,
        }
        localStorage.setItem(key, JSON.stringify(item))
      },

      get: function getWithExpiry(key) {
        const itemStr = localStorage.getItem(key)

        if (!itemStr) {
          return undefined
        }
        const item = JSON.parse(itemStr)
        const now = new Date()

        if (now.getTime() > item.expiry) {
          localStorage.removeItem(key)
          return undefined
        }
        return item.value
      }
    }
  
    win.getScript = url => new Promise((resolve, reject) => {
      const script = document.createElement('script')
      script.src = url
      script.async = true
      script.onerror = reject
      script.onload = script.onreadystatechange = function() {
        const loadState = this.readyState
        if (loadState && loadState !== 'loaded' && loadState !== 'complete') return
        script.onload = script.onreadystatechange = null
        resolve()
      }
      document.head.appendChild(script)
    })
  
      win.activateDarkMode = function () {
        document.documentElement.setAttribute('data-theme', 'dark')
        if (document.querySelector('meta[name="theme-color"]') !== null) {
          document.querySelector('meta[name="theme-color"]').setAttribute('content', '#0d0d0d')
        }
      }
      win.activateLightMode = function () {
        document.documentElement.setAttribute('data-theme', 'light')
        if (document.querySelector('meta[name="theme-color"]') !== null) {
          document.querySelector('meta[name="theme-color"]').setAttribute('content', '#ffffff')
        }
      }
      const t = saveToLocal.get('theme')
    
          if (t === 'dark') activateDarkMode()
          else if (t === 'light') activateLightMode()
        
      const asideStatus = saveToLocal.get('aside-status')
      if (asideStatus !== undefined) {
        if (asideStatus === 'hide') {
          document.documentElement.classList.add('hide-aside')
        } else {
          document.documentElement.classList.remove('hide-aside')
        }
      }
    
    const detectApple = () => {
      if(/iPad|iPhone|iPod|Macintosh/.test(navigator.userAgent)){
        document.documentElement.classList.add('apple')
      }
    }
    detectApple()
    })(window)</script><meta name="generator" content="Hexo 6.2.0"></head><body><div id="sidebar"><div id="menu-mask"></div><div id="sidebar-menus"><div class="avatar-img is-center"><img src="https://i.loli.net/2021/02/24/5O1day2nriDzjSu.png" onerror="onerror=null;src='/img/friend_404.gif'" alt="avatar"/></div><div class="sidebar-site-data site-data is-center"><a href="/blog/archives/"><div class="headline">文章</div><div class="length-num">8</div></a><a href="/blog/tags/"><div class="headline">标签</div><div class="length-num">2</div></a><a href="/blog/categories/"><div class="headline">分类</div><div class="length-num">1</div></a></div><hr/></div></div><div class="post" id="body-wrap"><header class="post-bg" id="page-header" style="background-image: url('')"><nav id="nav"><span id="blog_name"><a id="site-name" href="/blog/">梓琰苑</a></span><div id="menus"><div id="toggle-menu"><a class="site-page"><i class="fas fa-bars fa-fw"></i></a></div></div></nav><div id="post-info"><h1 class="post-title">Spring入门</h1><div id="post-meta"><div class="meta-firstline"><span class="post-meta-date"><i class="far fa-calendar-alt fa-fw post-meta-icon"></i><span class="post-meta-label">发表于</span><time class="post-meta-date-created" datetime="2022-06-22T10:06:45.824Z" title="发表于 2022-06-22 18:06:45">2022-06-22</time><span class="post-meta-separator">|</span><i class="fas fa-history fa-fw post-meta-icon"></i><span class="post-meta-label">更新于</span><time class="post-meta-date-updated" datetime="2018-11-05T09:28:01.000Z" title="更新于 2018-11-05 17:28:01">2018-11-05</time></span><span class="post-meta-categories"><span class="post-meta-separator">|</span><i class="fas fa-inbox fa-fw post-meta-icon"></i><a class="post-meta-categories" href="/blog/categories/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/">学习笔记</a></span></div><div class="meta-secondline"><span class="post-meta-separator">|</span><span class="post-meta-pv-cv" id="" data-flag-title="Spring入门"><i class="far fa-eye fa-fw post-meta-icon"></i><span class="post-meta-label">阅读量:</span><span id="busuanzi_value_page_pv"></span></span></div></div></div></header><main class="layout" id="content-inner"><div id="post"><article class="post-content" id="article-container"><p>[TOC]</p>
<h1 id="Spring入门"><a href="#Spring入门" class="headerlink" title="Spring入门"></a>Spring入门</h1><h2 id="使用Spring容器"><a href="#使用Spring容器" class="headerlink" title="使用Spring容器"></a>使用Spring容器</h2><p>Spring有两个核心接口，BeanFactory和ApplicationContext,其中ApplicationContext是BeanFactory的子接口。它们都可代表Spring容器，Spring容器是生成Bean实例的工厂，并管理容器中的Bean.</p>
<h3 id="Spring容器"><a href="#Spring容器" class="headerlink" title="Spring容器"></a>Spring容器</h3><p>BeanFactory是Spring最基本的容器，包含如下几个基本方法：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 判断Spring容器中是否包含id为name的Bean实例</span></span><br><span class="line"><span class="type">boolean</span> <span class="title function_">containsBean</span><span class="params">(String name)</span>;</span><br><span class="line"><span class="comment">// 获取Spring容器中输入requiredType类型的、唯一的Bean实例</span></span><br><span class="line">&lt;T&gt; T <span class="title function_">getBean</span><span class="params">(Class&lt;T&gt; requiredType)</span>;</span><br><span class="line"><span class="comment">// 返回容器id为name的Bean实例</span></span><br><span class="line">Object <span class="title function_">getBean</span><span class="params">(String name)</span>;</span><br><span class="line"><span class="comment">// 返回容器中id为name，并且类型类requiredType的Bean</span></span><br><span class="line">&lt;T&gt; T <span class="title function_">getBean</span><span class="params">(String name,class&lt;T&gt; requiredType)</span>;</span><br><span class="line"><span class="comment">// 返回容器中id为name的Bean实例的类型</span></span><br></pre></td></tr></table></figure>
<p>BeanFactory常用的实现类为DefaultListableBeanFactory</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 搜索类加载路径下的beans.xml文件创建Resource对象</span></span><br><span class="line"><span class="type">Resource</span> <span class="variable">isr</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ClassPathResource</span>(<span class="string">&quot;beans.xml&quot;</span>);</span><br><span class="line"><span class="type">DefaultListableBeanFactory</span> <span class="variable">beanFactory</span> <span class="operator">=</span>  <span class="keyword">new</span> <span class="title class_">DefaultListableBeanFactory</span>;</span><br><span class="line"><span class="keyword">new</span> <span class="title class_">XmlBeanDefinitionReader</span>(beanFactor).loadBeanDefinitions(isr);</span><br></pre></td></tr></table></figure>
<p>如果应用需要加载多个配置文件来创建Spring容器，则应该采用BeanFactory的子接口ApplicationContext来创建BeanFactory的实例。ApplicationContext接口包含FileSystemXmlApplicationContext和ClassXmlApplicationContext两个常用类，分别代表从类路径加载配置文件和从文件系统加载配置文件。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">ApplicationContext</span> <span class="variable">appContext</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ClassPathXmlApplicationContext</span>(<span class="string">&quot;beans.xml&quot;</span>, <span class="string">&quot;server.xml&quot;</span>);</span><br></pre></td></tr></table></figure>
<h3 id="使用ApplicationContext"><a href="#使用ApplicationContext" class="headerlink" title="使用ApplicationContext"></a>使用ApplicationContext</h3><p>ApplicationContext支持BeanFactory的全部功能，还支持如下额外功能：</p>
<blockquote>
<ul>
<li>ApplicationContext默认会初始化所有的singleton Bean,也可以通过配置取消初始化</li>
<li>ApplicationContext继承MessageSource接口，提供国际化支持</li>
<li>同时加载多份配置文件</li>
<li>事件机制</li>
<li>以声明方式启动并创建Spring容器</li>
</ul>
</blockquote>
<p>当系统创建ApplicationContext容器时，默认会预初始化所有的singleton Bean，所以系统前期创建ApplicationContenxt将消耗较大的系统开销，但一旦初始化完成，程序后面获取singleton Bean实例会有较好的性能。  </p>
<p>BeanFactory在创建时并不会初始化所有的Bean，只有在getBean方法显式调用时才会初始化Bean。  </p>
<p>ApplicationContext包括BeanFactory的全部功能，因此建议优先使用ApplicationContext。除非对于哪些内存非常关键的引用，才考虑使用BeanFactory.  </p>
<p>无可阻止Spring容器预初始化容器中的singleton Bean，可以为<code>&lt;bean.../&gt;</code>元素指定lazy-init&#x3D;”true”,该属性用于阻止预初始化该Bean</p>
<h3 id="ApplicationContext的事件支持"><a href="#ApplicationContext的事件支持" class="headerlink" title="ApplicationContext的事件支持"></a>ApplicationContext的事件支持</h3><p>ApplicationContext的事件机制是<strong>观察者模式</strong>的实现。如果容器中有一个ApplicationListener Bean,每当ApplicationContext发布ApplicationEvent时，ApplicationListeners Bean将自动触发</p>
<p>Spring的事件框架依赖如下两个重要成员：</p>
<blockquote>
<ul>
<li>ApplicationEvent：容器事件，必须由ApplicationContext发布</li>
<li>ApplicationListener：监听器，可由容器中的任何监听器Bean担任</li>
</ul>
<p>只要一个Java类继承了ApplicationEvent基类，那该对象就可以作为Spring容器的容器事件。</p>
</blockquote>
<p>容器事件的监听器类必须实现ApplicationListener接口，该接口必须实现如下方法：</p>
<blockquote>
<ul>
<li>onApplicationEvent(ApplicationEvent event)：每当容器内发生任何事件时，该方法自动被触发</li>
</ul>
</blockquote>
<p>在配置文件配置监听类Bean时，可省略id属性，Spring容器会自动识别该监听器  </p>
<p>当系统创建Spring容器、加载Spring容器时会触发容器事件，容器事件监听器可以监听到这些事件。程序也可调用ApplicaionContext的publicEvent()方法来主动触发容器事件。<br>如果开发者需要在Spring容器初始化、销毁时回调自定义方法，就可以通过事件监听器来实现。</p>
<blockquote>
<p>注：如果希望Bean发布容器事件，则必须让该Bean实现ApplicationContextAware或BeanFactoryAware接口，以获得对容器的引用。</p>
</blockquote>
<h3 id="让Bean获取Spring容器"><a href="#让Bean获取Spring容器" class="headerlink" title="让Bean获取Spring容器"></a>让Bean获取Spring容器</h3><p>为了让Spring获取它所在的Spring容器，可以让Bean实现BeanFactoryAware接口，实现如下方法：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">setBeanFactory(BeanFacotry beanFactory); <span class="comment">//方法中的参数指向创建它的BeanFactory</span></span><br></pre></td></tr></table></figure>
<p>类似的还有ApplicationContextAware接口，需实现的方法如下：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">setApplicationContext(ApplicationContext context); <span class="comment">//方法中的参数指向创建它的ApplicationContext</span></span><br></pre></td></tr></table></figure>
<p>Spring容器会检查所有的Bean，如果发现某个Bean实现了如上接口，将自己调用该Bean的setBeanFactory或setApplicaionContext方法将自身作为参数传递给该方法。</p>
<h2 id="容器中的Bean"><a href="#容器中的Bean" class="headerlink" title="容器中的Bean"></a>容器中的Bean</h2><h3 id="Bean的基本定义和Bean别名"><a href="#Bean的基本定义和Bean别名" class="headerlink" title="Bean的基本定义和Bean别名"></a>Bean的基本定义和Bean别名</h3><p><code>&lt;beans.../&gt;</code>元素是Spring配置文件的根元素，可以指定如下属性</p>
<blockquote>
<ul>
<li>default-lazy-init：指定该&lt;beans…&#x2F;&gt;元素下配置的所有Bean默认的延迟初始化行为</li>
<li>default-merge：指定该&lt;beans…&#x2F;&gt;元素下配置的所有Bean的merge行为</li>
<li>default-autowire：指定该&lt;beans…&#x2F;&gt;元素下配置的所有Bean默认的自动装配行为</li>
<li>default-autowire-candidates：指定该&lt;beans…&#x2F;&gt;元素下配置的所有Bean默认是否作为自动自动装配的候选Bean</li>
<li>default-init-method：指定该&lt;beans…&#x2F;&gt;元素下配置的所有Bean默认的初始化方法</li>
<li>default-destory-method：指定该&lt;beans…&#x2F;&gt;元素下配置的所有Bean默认的回收方法</li>
</ul>
</blockquote>
<p>在单个Bean中应用，只需将defalut去掉便可以应用于该Bean，&lt;bean…&#x2F;&gt;下指定的属性会覆盖&lt;beans…&#x2F;&gt;下指定的属性。</p>
<p>在定义Bean时，通常需指定如下两个属性：</p>
<blockquote>
<ul>
<li>id：确定该Bean在Spring容器中的唯一标识，容器对Bean的管理、访问，以及该Bean的依赖关系都依赖于此属性</li>
<li>class：指定该Bean的具体实现类，不能是接口。</li>
</ul>
</blockquote>
<p>id属性默认不能包含特殊字符，如*@&#x2F;等。可通过name属性指定别名使用</p>
<blockquote>
<ul>
<li>name：该属性指定一个Bean示例的标识名，表明将为该Bean示例指定别名</li>
<li>alias：指定一个别名</li>
</ul>
</blockquote>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;person&quot;</span> <span class="attr">class</span>=<span class="string">&quot;...&quot;</span> <span class="attr">name</span>=<span class="string">&quot;#abc,@123,abc*&quot;</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">alias</span> <span class="attr">name</span>=<span class="string">&quot;person&quot;</span> <span class="attr">alias</span>=<span class="string">&quot;jack&quot;</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">alias</span> <span class="attr">name</span>=<span class="string">&quot;jack&quot;</span> <span class="attr">alias</span>=<span class="string">&quot;jackee&quot;</span>/&gt;</span></span><br></pre></td></tr></table></figure>
<h3 id="容器中Bean的作用域"><a href="#容器中Bean的作用域" class="headerlink" title="容器中Bean的作用域"></a>容器中Bean的作用域</h3><p>Spring支持如下6种作用域：</p>
<blockquote>
<ul>
<li>singleton：单例模式，在整个SpringIoC容器中，该实例只生成一次。默认属性</li>
<li>prototype：每次通过同期的getBean()方法获取prototype作用域的Bean时，都会生成新的实例。</li>
<li>request：同一次请求中获取的Bean只生成一次</li>
<li>session：同一个会话中获取的Bean只生成一次</li>
<li>application：对于整个Web应用中获取的Bean为相同的实例</li>
<li>websocket：在整个WebSocket的通信过程中，只生成一个实例</li>
</ul>
</blockquote>
<p>常用的为singleton和pototype作用域，其它四种作用域只应用于Web环境中。<br>对于singleton作用域实例，由容器负责跟踪Bean实例的状态，负责该Bean的整个生命行为。对于prototype作用域的的Bean,容器只负责生成，一旦创建成功便不再跟踪</p>
<h3 id="配置依赖"><a href="#配置依赖" class="headerlink" title="配置依赖"></a>配置依赖</h3><blockquote>
<ul>
<li>设值注入：通过<code>&lt;property.../&gt;</code>元素驱动Spring执行setter方法</li>
<li>构造注入：通过<code>&lt;constructor-arg.../&gt;</code>元素驱动Spring执行带参数的构造器</li>
</ul>
</blockquote>
<p>通常不建议使用配置文件管理Bean的基本类型的属性值；通常只使用配置文件管理容器中Bean之间的依赖关系。<br>通过<code>&lt;constructor-arg.../&gt;</code>配置依赖时时根据参数顺序进行注入依赖，也可通过index属性显式指定参数顺序：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;Person&quot;</span> <span class="attr">class</span>=<span class="string">&quot;com.learn.Person&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">constructor-arg</span> <span class="attr">index</span>=<span class="string">&quot;1&quot;</span> <span class="attr">value</span>=<span class="string">&quot;35&quot;</span>/&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">constructor-arg</span> <span class="attr">index</span>=<span class="string">&quot;0&quot;</span> <span class="attr">value</span>=<span class="string">&quot;张三&quot;</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h3 id="设置普通属性值"><a href="#设置普通属性值" class="headerlink" title="设置普通属性值"></a>设置普通属性值</h3><p><code>&lt;value.../&gt;</code>元素用于指定基本类型及其包装、字符串类型的参数值，Spring通过XML解析器来解析出这些数据，然后利用java.beans.PropertyEditor完成类型转换：从String类型转换为所需的参数类型</p>
<h3 id="配置合作者Bean"><a href="#配置合作者Bean" class="headerlink" title="配置合作者Bean"></a>配置合作者Bean</h3><p><code>&lt;ref.../&gt;</code>元素用于指定所依赖的其它Bean，指定该Bean的id属性值</p>
<h3 id="使用自动装配注入合作者Bean"><a href="#使用自动装配注入合作者Bean" class="headerlink" title="使用自动装配注入合作者Bean"></a>使用自动装配注入合作者Bean</h3><p>autowire、default-autowire接收如下参数值：</p>
<blockquote>
<ul>
<li>no：不使用自动装配。Bean依赖必须通过ref显式配置。<strong>默认配置，不建议更改</strong></li>
<li>byName：根据setter方法名进行自动装配。Spring容器查找容器中的全部Bean，找出其id与setter方法名去掉set前缀，并小写首字母后同名的Bean来完成注入。如没有找到，则不会进行任何注入。</li>
<li>byType：根据setter方法的形参类型来自动匹配。Spring容器查找容器中的全部Bean，如果正好有一个Bean类型与setter方法的形参类型匹配，就自动注入这个Bean；如果找到多个这样的Bean，则抛出异常；如果没有找到，则什么都不会发生。</li>
<li>constructor：与byType类型，区别是用于自动匹配构造器的参数</li>
<li>autodetect：Spring容器根据Bean内部结构，自行决定使用constructor或byType策略。如果找到一个默认的构造参数，那么就会应用byType策略。</li>
</ul>
<p>当一个Bean既使用自动装配依赖，又使用ref显式指定依赖时，则显式指定的依赖覆盖自动装配的依赖。 </p>
</blockquote>
<p>如果希望将某些Bean排除在自动装配之外，不作为Spring自动装配策略的候选者，可<code>&lt;bean.../&gt;</code>设置该Bean的autowire-candidate属性为false。还可以通过在<code>&lt;beans.../&gt;</code>中指定default-autowire-candidates属性将一批Bean排除在自动装配之外（该属性值允许使用模式字符串，可指定多个模式字符串）。  </p>
<p>自动装配将Bean之间的耦合关系降低到代码层次，不利于高层次解耦；降低了依赖关系的透明性和清晰性。故在大型项目中不推荐使用自动装配。</p>
<h3 id="注入嵌套Bean"><a href="#注入嵌套Bean" class="headerlink" title="注入嵌套Bean"></a>注入嵌套Bean</h3><p>如果某个Bean所依赖的Bean不想被Spring容器直接访问，则可以使用嵌套Bean。<br>把<code>&lt;beans.../&gt;</code>配置成<code>&lt;property.../&gt;</code>或<code>&lt;constructor-ages.../&gt;</code>的子元素，那么该<code>&lt;beans.../&gt;</code>元素配置的Bean仅仅作为setter注入、构造注入的参数。由于容器不能获取嵌套Bean，因此可不需指定id属性。</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;chinese&quot;</span> <span class="attr">class</span>=<span class="string">&quot;org.learn.impl.Chinese&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;axe&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">bean</span> <span class="attr">class</span>=<span class="string">&quot;org.learn.impl.SteelAxe&quot;</span>/&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h3 id="注入集合值"><a href="#注入集合值" class="headerlink" title="注入集合值"></a>注入集合值</h3><p>如果需要使用形参为集合的setter方法，或调用形参为集合的构造器，则可使用集合元素&lt;list…&#x2F;&gt;、&lt;set…&#x2F;&gt;、&lt;map…&#x2F;&gt;、&lt;props…&#x2F;&gt;分别来设置类型为List、Set、Map和Properties的集合参数值。</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;chinese&quot;</span> <span class="attr">class</span>=<span class="string">&quot;org.learn.impl.Chinese&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;schools&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">list</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">value</span>&gt;</span>小学<span class="tag">&lt;/<span class="name">value</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">value</span>&gt;</span>中学<span class="tag">&lt;/<span class="name">value</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">value</span>&gt;</span>大学<span class="tag">&lt;/<span class="name">value</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">list</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;scores&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">map</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">entry</span> <span class="attr">key</span>=<span class="string">&quot;数学&quot;</span> <span class="attr">value</span>=<span class="string">&quot;87&quot;</span>/&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">entry</span> <span class="attr">key</span>=<span class="string">&quot;英语&quot;</span> <span class="attr">value</span>=<span class="string">&quot;90&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">map</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;phaseAxes&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">map</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">entry</span> <span class="attr">key</span>=<span class="string">&quot;原始社会&quot;</span> <span class="attr">value-ref</span>=<span class="string">&quot;stoneAxe&quot;</span>/&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">entry</span> <span class="attr">key</span>=<span class="string">&quot;农业社会&quot;</span> <span class="attr">value</span>=<span class="string">&quot;steelAxe&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">map</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;health&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">props</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">prop</span> <span class="attr">key</span>=<span class="string">&quot;血压&quot;</span>/&gt;</span>正常<span class="tag">&lt;/<span class="name">prop</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">prop</span> <span class="attr">key</span>=<span class="string">&quot;身高&quot;</span>/&gt;</span>175<span class="tag">&lt;/<span class="name">prop</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">props</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;axes&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">set</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">value</span>&gt;</span>字符串<span class="tag">&lt;/<span class="name">value</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">bean</span> <span class="attr">class</span>=<span class="string">&quot;...&quot;</span> /&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">ref</span> <span class="attr">bean</span>=<span class="string">&quot;stoneAxe&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">set</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p><code>&lt;list.../&gt;</code>、<code>&lt;set.../&gt;</code>、<code>&lt;key../&gt;</code>可接受如下子元素：</p>
<blockquote>
<ul>
<li>value：指定集合元素是基本数据类型或字符串类型值</li>
<li>ref：指定集合元素是容器中的另一个Bean示例</li>
<li>bean：指定集合元素是一个嵌套Bean</li>
<li>list、set、map及props：指定集合元素又是集合</li>
</ul>
</blockquote>
<p><code>&lt;props.../&gt;</code>元素用于配置Properties类型的参数值，其key和value只能是字符串</p>
<p><code>&lt;map.../&gt;</code>元素的<code>&lt;entry.../&gt;</code>子元素配置一组键值对，其支持如下属性:</p>
<blockquote>
<ul>
<li>key：如果Map key是基本类型或字符串</li>
<li>key-ref：如果Map key是容器中的另外一个Bean实例，使用该属性指定引用Bean的id</li>
<li>value：如果Map value是基本类型或字符串</li>
<li>value-ref：如果Map value是容器中的另外一个Bean实例，使用该属性指定引用Bean的id</li>
</ul>
</blockquote>
<p>SpringIoc容器支持集合的合并，子Bean中的集合属性值可以从其父Bean中的集合属性值继承和覆盖而来</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">beans</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;parent&quot;</span> <span class="attr">abstract</span>=<span class="string">&quot;true&quot;</span> <span class="attr">class</span>=<span class="string">&quot;org.learn.impl.ComplexObject&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;adminEmails&quot;</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">props</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">prop</span> <span class="attr">key</span>=<span class="string">&quot;admin&quot;</span>/&gt;</span>admin@163.com<span class="tag">&lt;/<span class="name">prop</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">prop</span> <span class="attr">key</span>=<span class="string">&quot;support&quot;</span>/&gt;</span>support@163.com<span class="tag">&lt;/<span class="name">prop</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;/<span class="name">props</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;child&quot;</span> <span class="attr">parent</span>=<span class="string">&quot;parent&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;adminEmails&quot;</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">props</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">prop</span> <span class="attr">key</span>=<span class="string">&quot;sales&quot;</span>/&gt;</span>sales@163.com<span class="tag">&lt;/<span class="name">prop</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">prop</span> <span class="attr">key</span>=<span class="string">&quot;support&quot;</span>/&gt;</span>support@163.com<span class="tag">&lt;/<span class="name">prop</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;/<span class="name">props</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">beans</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p>此时child Bean的adminEmails属性值通过继承和覆盖变为三个</p>
<h3 id="组合属性"><a href="#组合属性" class="headerlink" title="组合属性"></a>组合属性</h3><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;chinese&quot;</span> <span class="attr">class</span>=<span class="string">&quot;org.learn.impl.Chinese&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;foo.bar.x.y&quot;</span> <span class="attr">value</span>=<span class="string">&quot;xxxx&quot;</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p>对于这种注入组合属性值的形式，组合属性只有最后一个属性才调用setter方法，前面各属性实际上对应于调用getter方法。故除最后一个属性外，其他属性均不能为null</p>
<h2 id="Spring提供的Java配置管理"><a href="#Spring提供的Java配置管理" class="headerlink" title="Spring提供的Java配置管理"></a>Spring提供的Java配置管理</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Configuration</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">AppConfig</span></span><br><span class="line">&#123;</span><br><span class="line">  <span class="meta">@Value(&quot;孙悟空&quot;)</span> String personName;</span><br><span class="line">  </span><br><span class="line">  <span class="meta">@Bean(&quot;name=chinese&quot;)</span></span><br><span class="line">  <span class="keyword">public</span> Person <span class="title function_">person</span><span class="params">()</span></span><br><span class="line">  &#123;</span><br><span class="line">    <span class="type">Chinese</span> <span class="variable">p</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Person</span>();</span><br><span class="line">    p.setName(personName);</span><br><span class="line">    p.setAxe(stoneAxe());</span><br><span class="line">    <span class="keyword">return</span> p;</span><br><span class="line">  &#125;</span><br><span class="line">  </span><br><span class="line">  <span class="meta">@Bean(name=&quot;stoneAxe&quot;)</span></span><br><span class="line">  <span class="keyword">public</span> Axe <span class="title function_">stoneAxe</span><span class="params">()</span></span><br><span class="line">  &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">StoneAxe</span>();</span><br><span class="line">  &#125;</span><br><span class="line">  </span><br><span class="line">  <span class="meta">@Bean(name=&quot;steelAxe&quot;)</span></span><br><span class="line">  <span class="keyword">public</span> Axe <span class="title function_">steelAxe</span><span class="params">()</span></span><br><span class="line">  &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">SteelAxe</span>;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<blockquote>
<ul>
<li>@Configuration：用于修饰一个Java配置类</li>
<li>@Bean：用于修饰一个方法，将该方法的返回值定义成容器的一个Bean，可通过那么属性指定该 Bean 的 Id，name 属性可省略Id默认为方法名</li>
<li>@Value:用于修饰一个Field，用于为该Field配置一个值，相当于配置一个变量</li>
</ul>
</blockquote>
<p>一旦使用了Java配置类来管理Spring容器中的Bean及其依赖关系，此时就需要如下方式来创建Spring容器：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">ApplicationContext</span> <span class="variable">ctx</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">AnnotationConfigApplicationContext</span>(AppConfig.class);</span><br></pre></td></tr></table></figure>

<blockquote>
<ul>
<li>@Import：修饰一个Java配置类，用于向当前Java配置类中导入其他Java配置类</li>
<li>@Scope：用于修饰一个方法，指定该方法对应的Bean的作用域</li>
<li>@Lazy：用于修饰一个方法，指定该方法对应的Bean是否需要延迟初始化</li>
<li>@DependsOn：用于修饰一个方法，指定在初始化该方法对应的Bean之前先初始化指定的Bean</li>
</ul>
</blockquote>
<p>可混合使用XML配置文件和Java配置类</p>
<blockquote>
<ol>
<li><p>如果以XML配置为主，就需要让XML配置文件能加载Java类配置。在XML中增加如下代码:  </p>
 <figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!-- 导入其他 Bean 配置 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">import</span> <span class="attr">resource</span>=<span class="string">&quot;beans.xml&quot;</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">context:annotation-config</span>/&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- 加载Java配置类--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">class</span>=<span class="string">&quot;org.learn.app.config.AppConfig&quot;</span>/&gt;</span></span><br></pre></td></tr></table></figure>
</li>
<li><p>如果以Java配置为主，就需要让Java配置类能加载XML配置。需要使用@ImportResource注解，导入指定的XML配置文件：<br>​</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Configuration</span></span><br><span class="line"><span class="meta">@ImportResource(&quot;classpath:/beans.xml&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">AppConfig</span></span><br><span class="line">&#123;</span><br><span class="line">  .....</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li>
</ol>
</blockquote>
<h2 id="创建Bean的3种方式"><a href="#创建Bean的3种方式" class="headerlink" title="创建Bean的3种方式"></a>创建Bean的3种方式</h2><h3 id="使用构造器创建Bean实例"><a href="#使用构造器创建Bean实例" class="headerlink" title="使用构造器创建Bean实例"></a>使用构造器创建Bean实例</h3><h3 id="使用静态工厂创建Bean"><a href="#使用静态工厂创建Bean" class="headerlink" title="使用静态工厂创建Bean"></a>使用静态工厂创建Bean</h3><p>使用静态工厂方法创建Bean实例时，class属性指向静态工厂类，Spring通过该属性知道是哪个工厂类来创建Bean实例。使用factory-method指定工厂方法，此方法必须是静态的。如果静态工厂需要参数，则使用&lt;constructor-arg…&#x2F;&gt;元素传入。</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;dog&quot;</span> <span class="attr">class</span>=<span class="string">&quot;org.learn.app.BeingFactory&quot;</span> <span class="attr">factory-method</span>=<span class="string">&quot;getBeing&quot;</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- 配置静态工厂方法的参数 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">constructor-age</span> <span class="attr">value</span>=<span class="string">&quot;dog&quot;</span>/&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- 驱动Spring以“我是狗”为参数来执行dog的setMsg方法 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;msg&quot;</span> <span class="attr">value</span>=<span class="string">&quot;我是狗&quot;</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p>在这个过程中，Spring不再负责创建Bean实例，Bean实例时由用户提供的静态工厂类提供创建的。当静态工厂方法创建了Bean实例后，Spring依然可以管理该Bean实例的的依赖关系，包括为其注入所需的依赖Beean、管理其生命周期等。</p>
<h3 id="调用实例工厂方法创建Bean"><a href="#调用实例工厂方法创建Bean" class="headerlink" title="调用实例工厂方法创建Bean"></a>调用实例工厂方法创建Bean</h3><p>使用实例工厂方法时，配置Bean实例的&lt;bean…&#x2F;&gt;元素无须class属性，因为Spring容器不再直接实例化该Bean,Spring容器仅仅调用实例工厂的工厂方法，工厂方法负责创建Bean实例。需指定如下参数：</p>
<blockquote>
<ul>
<li>factory-bean：该属性的值为工厂Bean的id</li>
<li>factory-method：该属性指定实例工厂的工厂方法</li>
</ul>
</blockquote>
<p>如果需要在调用实例方法时传入参数，则使用&lt;constructor-arg…&gt;元素指定参数值</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;personFactory&quot;</span> <span class="attr">class</span>=<span class="string">&quot;org.learn.factory.PersonFactory&quot;</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;chinese&quot;</span> <span class="attr">factory-method</span>=<span class="string">&quot;personFactory&quot;</span> <span class="attr">factory-method</span>=<span class="string">&quot;getPerson&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">constructor-arg</span> <span class="attr">value</span>=<span class="string">&quot;chin&quot;</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h2 id="深入理解容器中的Bean"><a href="#深入理解容器中的Bean" class="headerlink" title="深入理解容器中的Bean"></a>深入理解容器中的Bean</h2><h3 id="抽象Bean与子Bean"><a href="#抽象Bean与子Bean" class="headerlink" title="抽象Bean与子Bean"></a>抽象Bean与子Bean</h3><p>将多个&lt;bean…&#x2F;&gt;配置中相同的信息提取出来，指定&lt;bean…&#x2F;&gt;中的abstract属性为tru,集中成配置模板—这个模板不是真正的Bean，不能被实例化。抽象Bean的价值在于被继承，抽象Bean通常作为父Bean被继承。抽象Bean可不指定class属性。</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">beans</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;personTemp&quot;</span> <span class="attr">abstract</span>=<span class="string">&quot;true&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;name&quot;</span> <span class="attr">value</span>=<span class="string">&quot;张三&quot;</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;axe&quot;</span> <span class="attr">ref</span>=<span class="string">&quot;steelAxe&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;chinese&quot;</span> <span class="attr">class</span>=<span class="string">&quot;org.learn.impl.Chinese&quot;</span> <span class="attr">parent</span>=<span class="string">&quot;personTemp&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;american&quot;</span> <span class="attr">class</span>=<span class="string">&quot;org.learn.impl.Chinese&quot;</span> <span class="attr">parent</span>=<span class="string">&quot;personTemp&quot;</span>/&gt;</span></span><br></pre></td></tr></table></figure>
<p>当子Bean指定的配置信息与父Bean模板所指定的配置信息不一致时，子Bean所指定的配置信息将覆盖父Bean所指定的配置信息。子Bean无法从父Bean中继承如下属性：depends-on、autowire、singleton、scope、lazy-init。<br>如果父Bean指定了class属性，那么子Bean连class属性都可以省略，子Bean将采用与父Bean相同的实现类。</p>
<blockquote>
<p>注:此处的抽象与继承和Java中的抽象继承无关，只是配置文件模板化、复用。</p>
</blockquote>
<h3 id="容器中的工厂Bean"><a href="#容器中的工厂Bean" class="headerlink" title="容器中的工厂Bean"></a>容器中的工厂Bean</h3><p>FactoryBean接口是工厂Bean的标准接口，把工厂Bean（实现BeanFactory接口的Bean）部署在容器中之后，如果程序通过getBean()方法来获取它时，容器返回的不是FactoryBean实现类的实例，而是返回FactoryBean的产品（即该工厂Bean的getObject()方法的返回值）。<br>FactoryBean接口提供如下三个方法:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">T <span class="title function_">getObject</span><span class="params">()</span>; <span class="comment">//实现该方法负责返回该工厂Bean生成的Java实例</span></span><br><span class="line">Class&lt;?&gt; getObjectType(); <span class="comment">//实现该方法返回该工厂Bean生成的Java实例的实现类</span></span><br><span class="line"><span class="type">boolean</span> <span class="title function_">isSingleton</span><span class="params">()</span>; <span class="comment">//实现该方法表示该工厂Bean生成的Java实例是否为单例模式 </span></span><br></pre></td></tr></table></figure>
<p>配置FactoryBean与配置普通Bean的定义没有区别，但当程序向Spring容器请求该Bean时，容器返回该BeanFactoryBean的产品，而不是返回该FactoryBean本身。<br>当程序需要获得FactoryBean本身时，并不是直接请求Bean id，而是在Bean id前增加&amp;符号，容器则返回FactoryBean本身，而不是它生产的Bean。</p>
<h3 id="获得Bean自身的id"><a href="#获得Bean自身的id" class="headerlink" title="获得Bean自身的id"></a>获得Bean自身的id</h3><p>如果开发Bean时需要预知该Bean的配置id,则可实现BeanNameAware接口，通过该接口即可提前预知该Bean的配置id。BeanNameAware提供如下方法：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">setBeanName(String name); <span class="comment">//该方法的name参数就是Bean的配置id</span></span><br></pre></td></tr></table></figure>
<p>此接口的setter方法会由Spring容器自动调用，将部署该Bean的id属性作为参数传入。</p>
<h3 id="强制初始化Bean"><a href="#强制初始化Bean" class="headerlink" title="强制初始化Bean"></a>强制初始化Bean</h3><p>为了显式指定被依赖Bean在目标Bean之前初始化，可以使用depends-on属性，该属性可以在初始化主调Bean之前，强制初始化一个或多个Bean</p>
<h3 id="依赖关系注入之后的行为"><a href="#依赖关系注入之后的行为" class="headerlink" title="依赖关系注入之后的行为"></a>依赖关系注入之后的行为</h3><p>Spring提供两种方式在Bean全部属性设置成功后执行特定行为：</p>
<blockquote>
<ul>
<li>使用init-method属性<br>使用init-method属性指定某个方法在Bean全部依赖关系设置结束后自动执行。使用这种方式不需要将代码将Spring的接口耦合在一起，代码污染小。<em><strong>推荐使用</strong></em></li>
<li>实现InitializingBean接口<br>达到同样的效果，要求Bean必须继承InitializingBean接口，该接口提供一个方法 —void afterPropertiesSet() throws Excepion;&gt;</li>
</ul>
</blockquote>
<p>如果同时使用两种方式，则Spring容器先执行InitializingBean接口中定义的方法，然后执行init-method属性指定的方法。</p>
<h3 id="Bean销毁之前的行为"><a href="#Bean销毁之前的行为" class="headerlink" title="Bean销毁之前的行为"></a>Bean销毁之前的行为</h3><p>Spring同样提供两张方式定制Bean实例销毁之前的特定行为：</p>
<blockquote>
<ul>
<li>使用destory-method属性<br>使用destory-method属性指定某个方法在Bean销毁之前自动执行。使用这种方式不需要将代码将Spring的接口耦合在一起，代码污染小。<em><strong>推荐使用</strong></em></li>
<li>实现DisposableBean接口<br>可以实现同样的效果，但必须实现DisposableBean接口，该接口提供void destory() throw Exception;</li>
</ul>
</blockquote>
<p>如果同时使用两种方式，则Spring容器先执行DisposableBean接口中定义的方法，然后执行destory-method属性指定的方法。</p>
<p>如果处于一个非Web应用的环境下，为了让Spring容器优雅地关闭，并调用singleton Bean相应的析构回调方法，则需要在JVM里注册一个关闭钩子。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">BeanTest</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span></span><br><span class="line">    &#123;</span><br><span class="line">        <span class="type">AbstractApplicationContext</span> <span class="variable">ctx</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ClassPathXmlApplicationContext</span>(<span class="string">&quot;beans.xml&quot;</span>);</span><br><span class="line">        <span class="type">Person</span> <span class="variable">p</span> <span class="operator">=</span> ctx.getBean(<span class="string">&quot;chinese&quot;</span>, Person.class);</span><br><span class="line">        p.useAxe();</span><br><span class="line">        </span><br><span class="line">        <span class="comment">//为Spring容器注册关闭钩子</span></span><br><span class="line">        ctx.registerShutdownHook();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>如果在&lt;beans…&#x2F;&gt;中指定了default-init-method&#x3D;”init”，意味着只要Spring容器中的Bean实例具有init()方法，Spring就会在该Spring的所有依赖关系被设置之后，自动调用该Bena实例的init方法。</p>
<h3 id="协调作用域不同的步的Bean"><a href="#协调作用域不同的步的Bean" class="headerlink" title="协调作用域不同的步的Bean"></a>协调作用域不同的步的Bean</h3><p>当prototype作用域的Bean依赖singleton作用域的Bean时，使用Spring提供的依赖注入进行管理即可。<br>当singleton作用域的Bean依赖prototype作用域的Bean时，一旦singleton Bean初始化完成，它就持有了一个prototype Bean，容器再也不会为singleton Bean执行注入了。解决此问题有如下方法：</p>
<blockquote>
<ul>
<li>放弃依赖注入：singleton作用域的Bean每次需要prototype作用域的Bean时，主动向容器请新的Bean实例，即可保证每次注入的prototype Bean实例都是最新的实例</li>
<li>利用方法注入</li>
</ul>
</blockquote>
<p>使用lookup方法注入可以让Spring容器重写容器中Bean的抽象或具体方法，返回查找容器中其他Bean的结果，被查找的Bean通常是一个non-singleton Bean（尽管可以是一个singleton的）。Spring通过使用JDK动态代理或cglib库修改客户端的二进制码，从而实现上述要求。<br>为了实现lookup方法注入，大致需要如下两步：</p>
<blockquote>
<ol>
<li>将调用者Bean的实现类定义为抽象类，并定义一个抽象方法来获取被依赖的Bean</li>
<li>在&lt;bean…&#x2F;&gt;元素中添加&lt;lookup-method…&#x2F;&gt;子元素让Spring为调用者Bean的实现类实现指定的抽象方法。</li>
</ol>
</blockquote>
<p>&lt;lookup-method…&#x2F;&gt;元素需要如下两个属性：</p>
<blockquote>
<ul>
<li>name：指定需要让Spring实现的方法</li>
<li>bean：指定Spring实现该方法的返回值</li>
</ul>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">abstract</span> <span class="keyword">class</span> <span class="title class_">Chinese</span> </span><br><span class="line">&#123;</span><br><span class="line">    <span class="keyword">private</span> Dog dog;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">abstract</span> Dog <span class="title function_">getDog</span><span class="params">()</span>;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">hunt</span><span class="params">()</span></span><br><span class="line">    &#123;</span><br><span class="line">        getDog().run();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;personTemp&quot;</span> <span class="attr">abstract</span>=<span class="string">&quot;true&quot;</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- Spring只要检测到lookup-method元素，Spring会自动为该元素的name属性指定的方法提供实现体 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">lookup-method</span> <span class="attr">name</span>=<span class="string">&quot;getDog&quot;</span> <span class="attr">bean</span>=<span class="string">&quot;gunDog&quot;</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;gunDog&quot;</span> <span class="attr">class</span>=<span class="string">&quot;org.leanrn.impl.GunDog&quot;</span> <span class="attr">scope</span>=<span class="string">&quot;prototype&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;name&quot;</span> <span class="attr">value</span>=<span class="string">&quot;旺财&quot;</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p>Spring会采用运行时动态增强的方式来实现&lt;lookup-method…&#x2F;&gt;元素所指定的抽象方法，如果目标抽象类实现过接口，Spring会采用JDK动态代理来实现该抽象类，并为之实现抽象方法；如果目标抽象类没有实现过接口，Spring会采用cglib实现该抽象类，并为之实现抽象方法。</p>
<p>要保证&lt;lookup-method…&#x2F;&gt;方法注入每次都产生新的Bean实例，必须将目标Bean部署成prototype作用于；否则，如果容器中只有一个被依赖的Bean实例，即使采用lookup方法注入，每次也依然返回同一个Bean实例。</p>
<h2 id="高级依赖关系配置"><a href="#高级依赖关系配置" class="headerlink" title="高级依赖关系配置"></a>高级依赖关系配置</h2><h3 id="获取其他Bean的属性值"><a href="#获取其他Bean的属性值" class="headerlink" title="获取其他Bean的属性值"></a>获取其他Bean的属性值</h3><p>PropertyPathFactoryBean用来获取目标Bean的属性值（实际上就是它的getter方法的返回值），获得的值可注入其他Bean，也可直接定义成新的Bean。使用PropertyPathFactoryBean调用其他Bean的getter方法需要指定如下信息：</p>
<blockquote>
<p>调用哪个对象。由PropertyPathFactoryBean的setTargetObject(Object targetObject)方法指定；<br>调用哪个getter方法。由PropertyPathFactoryBean的setPropertyPath(String propertyPath)方法指定；</p>
</blockquote>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!-- target bean to be referenced by name --&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;tb&quot;</span> <span class="attr">class</span>=<span class="string">&quot;org.springframework.beans.TestBean&quot;</span> <span class="attr">singleton</span>=<span class="string">&quot;false&quot;</span>&gt;</span></span><br><span class="line">   <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;age&quot;</span> <span class="attr">value</span>=<span class="string">&quot;10&quot;</span>/&gt;</span></span><br><span class="line">   <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;spouse&quot;</span>&gt;</span></span><br><span class="line">     <span class="tag">&lt;<span class="name">bean</span> <span class="attr">class</span>=<span class="string">&quot;org.springframework.beans.TestBean&quot;</span>&gt;</span></span><br><span class="line">       <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;age&quot;</span> <span class="attr">value</span>=<span class="string">&quot;11&quot;</span>/&gt;</span></span><br><span class="line">     <span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br><span class="line">   <span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br><span class="line"></span><br><span class="line"> <span class="comment">&lt;!-- will result in 12, which is the value of property &#x27;age&#x27; of the inner bean --&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;propertyPath1&quot;</span> <span class="attr">class</span>=<span class="string">&quot;org.springframework.beans.factory.config.PropertyPathFactoryBean&quot;</span>&gt;</span></span><br><span class="line">   <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;targetObject&quot;</span>&gt;</span></span><br><span class="line">     <span class="tag">&lt;<span class="name">bean</span> <span class="attr">class</span>=<span class="string">&quot;org.springframework.beans.TestBean&quot;</span>&gt;</span></span><br><span class="line">       <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;age&quot;</span> <span class="attr">value</span>=<span class="string">&quot;12&quot;</span>/&gt;</span></span><br><span class="line">     <span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br><span class="line">   <span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br><span class="line">   <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;propertyPath&quot;</span> <span class="attr">value</span>=<span class="string">&quot;age&quot;</span>/&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br><span class="line"></span><br><span class="line"> <span class="comment">&lt;!-- will result in 11, which is the value of property &#x27;spouse.age&#x27; of bean &#x27;tb&#x27; --&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;propertyPath2&quot;</span> <span class="attr">class</span>=<span class="string">&quot;org.springframework.beans.factory.config.PropertyPathFactoryBean&quot;</span>&gt;</span></span><br><span class="line">   <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;targetBeanName&quot;</span> <span class="attr">value</span>=<span class="string">&quot;tb&quot;</span>/&gt;</span></span><br><span class="line">   <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;propertyPath&quot;</span> <span class="attr">value</span>=<span class="string">&quot;spouse.age&quot;</span>/&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br><span class="line"></span><br><span class="line"> <span class="comment">&lt;!-- will result in 10, which is the value of property &#x27;age&#x27; of bean &#x27;tb&#x27; --&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;tb.age&quot;</span> <span class="attr">class</span>=<span class="string">&quot;org.springframework.beans.factory.config.PropertyPathFactoryBean&quot;</span>/&gt;</span></span><br></pre></td></tr></table></figure>
<p>可以使用&lt;util:property-path…&gt;作为PropertyPathFactoryBean的简化配置，需要如下两个属性:</p>
<blockquote>
<ul>
<li>id：该属性指定将getter方法的返回值定义成名为id的Bean的实例</li>
<li>path：该属性指定将哪个Bean实例、哪个属性（支持复合属性）暴露出来</li>
</ul>
</blockquote>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!-- will result in 10, which is the value of property &#x27;age&#x27; of bean &#x27;tb&#x27; --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">util:property-path</span> <span class="attr">id</span>=<span class="string">&quot;name&quot;</span> <span class="attr">path</span>=<span class="string">&quot;testBean.age&quot;</span>/&gt;</span></span><br></pre></td></tr></table></figure>

<p>PropertyPathFactoryBean就是工厂Bean，在这种配置方式下，配置PropertyPathFactoryBean工厂Bean时指定的id属性，并不是该Bean的唯一标识，而是用于指定属性表达式的值。</p>
<h3 id="获取Field值"><a href="#获取Field值" class="headerlink" title="获取Field值"></a>获取Field值</h3><p>通过FieldRetrievingFactoryBean类，可访问类的静态Field或对象的实例Field值。FieldRetrievingFactoryBean获得指定Field的值之后，即可将获取的值注入其他Bean，也可直接定义成新的Bean。使用FieldRetrievingFactoryBean分一下两种情况：</p>
<blockquote>
<ul>
<li>如果要访问的Field是静态Field,则需要指定:<blockquote>
<p>调用哪个类。由FieldRetrievingFactoryBean的setTargetClass(String targeClass)方法指定；<br>访问哪个Field。由FieldRetrievingFactoryBean的setTargetField(String targetField)方法指定。</p>
</blockquote>
</li>
<li>如果要访问的Field是实例Field（要求实例Field以public修饰），则需要指定：<blockquote>
<p>调用哪个对象。由FieldRetrievingFactoryBean的setTargetObject(Object targetObject)方法指定<br>访问哪个Field。由FieldRetrievingFactoryBean的setTargetField(String targetField)方法指定。<br> FieldRetrievingFactoryBean还提供了一个setStaticField(String staticField)方法，该方法可同时指定获取哪个类的哪个静态Field的值。</p>
</blockquote>
</li>
</ul>
</blockquote>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">// standard definition for exposing a static field, specifying the &quot;staticField&quot; property</span><br><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;myField&quot;</span> <span class="attr">class</span>=<span class="string">&quot;org.springframework.beans.factory.config.FieldRetrievingFactoryBean&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;staticField&quot;</span> <span class="attr">value</span>=<span class="string">&quot;java.sql.Connection.TRANSACTION_SERIALIZABLE&quot;</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br><span class="line"></span><br><span class="line">// convenience version that specifies a static field pattern as bean name</span><br><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;java.sql.Connection.TRANSACTION_SERIALIZABLE&quot;</span></span></span><br><span class="line"><span class="tag">      <span class="attr">class</span>=<span class="string">&quot;org.springframework.beans.factory.config.FieldRetrievingFactoryBean&quot;</span>/&gt;</span></span><br></pre></td></tr></table></figure>

<p><code>&lt;util:constant.../&gt;</code>元素可作为FieldRetrievingFactoryBean访问静态Field的简化配置，使用该元素时可指定如下两个属性：</p>
<blockquote>
<ul>
<li>id：该属性指定将静态Field的值定义成名为id的Bean实例</li>
<li>static-field：该属性指定访问哪个类的哪个静态Field</li>
</ul>
</blockquote>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">util:constant</span> <span class="attr">static-field</span>=<span class="string">&quot;java.sql.Connection.TRANSACTION_SERIALIZABLE&quot;</span>/&gt;</span></span><br></pre></td></tr></table></figure>

<h3 id="获取方法返回值"><a href="#获取方法返回值" class="headerlink" title="获取方法返回值"></a>获取方法返回值</h3><p>通过MethodInvokingFactoryBean工厂Bean可以调用任意类的类方法，也可调用任意对象的实例方法，如果调用的方法有返回值，既可将该指定方法的返回值定义成容器中的Bean，也可将指定方法的返回值注入给其他Bean。使用MethodInvokingFactoryBean分一下两种情况：</p>
<blockquote>
<ul>
<li>如果希望调用的方法时静态方法，则需要指定：<blockquote>
<p>调用哪个类。通过MethodInvokingFactoryBean的setTargetClass(String targetClass)方法指定；<br>调用哪个方法。通过MethodInvokingFactoryBean的setTargetMethod(String targetMethod)方法指定；<br>调用方法的参数。通过MethodInvokingFactoryBean的 setArguments(Object[] arguments)方法指定。</p>
</blockquote>
</li>
<li>如果希望调用的方法是实例方法，则需要指定：<blockquote>
<p>调用哪个对象。通过MethodInvokingFactoryBean的 setTargetObject(Object targetObject)指定；<br>调用哪个方法。通过MethodInvokingFactoryBean的setTargetMethod(String targetMethod)方法指定；<br>调用方法的参数。通过MethodInvokingFactoryBean的 setArguments(Object[] arguments)方法指定。</p>
</blockquote>
</li>
</ul>
</blockquote>
<p>bean定义的一个示例（在基于XML的bean工厂定义中），它使用此类来调用静态工厂方法：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;myObject&quot;</span> <span class="attr">class</span>=<span class="string">&quot;org.springframework.beans.factory.config.MethodInvokingFactoryBean&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;staticMethod&quot;</span> <span class="attr">value</span>=<span class="string">&quot;com.whatever.MyClassFactory.getInstance&quot;</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p>调用静态方法然后使用实例方法获取Java系统属性的示例</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;sysProps&quot;</span> <span class="attr">class</span>=<span class="string">&quot;org.springframework.beans.factory.config.MethodInvokingFactoryBean&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;targetClass&quot;</span> <span class="attr">value</span>=<span class="string">&quot;java.lang.System&quot;</span>/&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;targetMethod&quot;</span> <span class="attr">value</span>=<span class="string">&quot;getProperties&quot;</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;javaVersion&quot;</span> <span class="attr">class</span>=<span class="string">&quot;org.springframework.beans.factory.config.MethodInvokingFactoryBean&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;targetObject&quot;</span> <span class="attr">ref</span>=<span class="string">&quot;sysProps&quot;</span>/&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;targetMethod&quot;</span> <span class="attr">value</span>=<span class="string">&quot;getProperty&quot;</span>/&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;arguments&quot;</span> <span class="attr">value</span>=<span class="string">&quot;java.version&quot;</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h2 id="基于XML-Schema-的简化配置方式"><a href="#基于XML-Schema-的简化配置方式" class="headerlink" title="基于XML Schema 的简化配置方式"></a>基于XML Schema 的简化配置方式</h2><h3 id="使用-p-命名空间简化配置-简化设值注入"><a href="#使用-p-命名空间简化配置-简化设值注入" class="headerlink" title="使用 p:命名空间简化配置(简化设值注入)"></a>使用 p:命名空间简化配置(简化设值注入)</h3><p>需要导入 XML Schema 里的 p:命名空间<code>xmlns:p=&quot;http://www.springframework.org/shema/p&quot;</code></p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;chinese&quot;</span> <span class="attr">class</span>=<span class="string">&quot;org.learn.impl.Chinese&quot;</span> <span class="attr">p:age</span>=<span class="string">&quot;29&quot;</span> <span class="attr">p:axe-ref</span>=<span class="string">&quot;stoneAxe&quot;</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;stoneAxe&quot;</span> <span class="attr">class</span>=<span class="string">&quot;org.learn.impl.StoneAxe&quot;</span>/&gt;</span></span><br></pre></td></tr></table></figure>
<h3 id="使用c-命名控件简化配置（简化构造注入）"><a href="#使用c-命名控件简化配置（简化构造注入）" class="headerlink" title="使用c:命名控件简化配置（简化构造注入）"></a>使用c:命名控件简化配置（简化构造注入）</h3><p>需要导入 XML Schema 里的 c:命名空间<code>xmlns:c=&quot;http://www.springframework.org/shema/c</code></p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;chinese&quot;</span> <span class="attr">class</span>=<span class="string">&quot;org.learn.impl.Chinese&quot;</span> <span class="attr">c:age</span>=<span class="string">&quot;29&quot;</span> <span class="attr">c:axe-ref</span>=<span class="string">&quot;stoneAxe&quot;</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;stoneAxe&quot;</span> <span class="attr">class</span>=<span class="string">&quot;org.learn.impl.StoneAxe&quot;</span>/&gt;</span></span><br></pre></td></tr></table></figure>
<p>可使用 c_N 的方式指定构造器参数位置。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;bean id=&quot;chinese&quot; class=&quot;org.learn.impl.Chinese&quot; c:_0=&quot;29&quot; c:_1-ref=&quot;stoneAxe&quot;/&gt;</span><br></pre></td></tr></table></figure>

<h3 id="使用-util-命名空间简化配置"><a href="#使用-util-命名空间简化配置" class="headerlink" title="使用 util:命名空间简化配置"></a>使用 util:命名空间简化配置</h3><p>需要导入 XML Schema 里的 util:命名空间 <code>xmlns:util=&quot;http://www.springframework.org/shema/util</code></p>
<blockquote>
<p>constant：该元素用于获取指定类的静态 Field<br>property-path：该元素用于获取指定对象的 getter 方法的返回值<br>list：该元素用于定一个一个 List Bean，支持使用&lt;value…&#x2F;&gt;、&lt;ref…&#x2F;&gt;、&lt;bean…&#x2F;&gt;等子元素来定义 List 集合元素。该标签支持如下三个属性：</p>
<blockquote>
<ul>
<li>id :该属性指定定一个名为 id 的 List Bean 实例</li>
<li>list-class：该属性指定 Spring 通过那个 List 实现类来创建 Bean 实例。默认使用 ArrayList</li>
<li>scope：指定该 List Bean 的作用域</li>
</ul>
</blockquote>
<p>set：该元素用于定一个一个 Set Bean，支持使用&lt;value…&#x2F;&gt;、&lt;ref…&#x2F;&gt;、&lt;bean…&#x2F;&gt;等子元素来定义 Set 集合元素。该标签支持如下三个属性：</p>
<blockquote>
<ul>
<li>id :该属性指定定一个名为 id 的 Set Bean 实例</li>
<li>set-class：该属性指定 Spring 通过那个 Set 实现类来创建 Bean 实例。默认使用 HashSet</li>
<li>scope：指定该 Set Bean 的作用域</li>
</ul>
</blockquote>
<p>map：该元素用于定一个一个 Map Bean，支持使用&lt;entry…&#x2F;&gt;元素来定义 Map 的键值对。该标签支持如下三个属性：<br> &gt; + id :该属性指定定一个名为 id 的 Map Bean 实例</p>
<blockquote>
<ul>
<li>map-class：该属性指定 Spring 通过那个 Map 实现类来创建 Bean 实例。默认使用 HashMap</li>
<li>scope：指定该 Map Bean 的作用域</li>
</ul>
</blockquote>
<p>properties：该元素用于加载一份资源文件，并根据加载的资源文件创建一个 Properties Bean 实例。该标签支持如下三个属性：</p>
<blockquote>
<ul>
<li>id :该属性指定定一个名为 id 的 Properties Bean 实例</li>
<li>location：指定资源文件的位置</li>
<li>scope：指定该 Properties Bean 的作用域</li>
</ul>
</blockquote>
</blockquote>
<h3 id="SpEL-语法详述"><a href="#SpEL-语法详述" class="headerlink" title="SpEL 语法详述"></a>SpEL 语法详述</h3><ol>
<li>直接量表达式<br> <code>&#123;3.14159&#125;</code> <code>&#123;&#39;Hello&#39;&#125;</code> <code>&#123;false&#125;</code></li>
<li>引用 bean、属性和方法<br> SpEL 通过 ID 引用其它的 Bean<code>&#123;sgtPeppers&#125;</code><br><br> 引用 Bean 中的属性<code>&#123;sgtPeppers.artist&#125;</code><br><br> 引用 Bean 中的方法<code>&#123;sgtPeppers.selectArtist()&#125;</code></li>
<li>安全导航<br> <code>&#123;foo?.bar&#125;</code> 先判断 foo是否为 null，如果 foo 为 null 就直接返回 null</li>
<li>在表达式中使用类型<br> <code>&#123;T(java.lang.math).PI&#125;</code>这里的 T()运算符的结果会是一个 Class 对象，表示访问类作用域的方法和常量</li>
<li>运算符<br> <code>&#123;2 * T(java.lang.Math).PI * circle.radius&#125;</code><br> <code>&#123;disc.title ?: &#39;Hello World&#39;&#125;</code>此处的?:表示判断 disc.title 是否为 null，如果为 null 的话指定默认值为 Hello World</li>
<li>计算集合<br> <code>&#123;jukebox.songs[4].title&#125;</code> 表示查询 jukebox 中 songs 集合的第5个元素的 title,此处[]中表示第几个元素<br> <code>&#123;jukebox.songs.?[artist eq &#39;Hello&#39;]&#125;</code> 此处的.?[]运算符表示对指定集合过滤，得到集合的一个子集<br> <code>&#123;jukebox.songs.^[artist eq &#39;Hello&#39;]&#125;</code>和<code>jukebox.songs.?[artist eq &#39;Hello&#39;]</code>此处中.^[]和.$[]分别表示查询集合中的第一个匹配项和最后一个匹配项<br> <code>jukebox.songs.![title]</code>此处的.![]是投影运算符，表示将集合的每个成员中选择特定的属性放到另外一个集合中。</li>
</ol>
</article><div class="post-copyright"><div class="post-copyright__author"><span class="post-copyright-meta">文章作者: </span><span class="post-copyright-info"><a href="http://yzb317415.gitee.io/blog">Milk Yang</a></span></div><div class="post-copyright__type"><span class="post-copyright-meta">文章链接: </span><span class="post-copyright-info"><a href="http://yzb317415.gitee.io/blog/2022/06/22/Spring%E5%85%A5%E9%97%A8/">http://yzb317415.gitee.io/blog/2022/06/22/Spring%E5%85%A5%E9%97%A8/</a></span></div><div class="post-copyright__notice"><span class="post-copyright-meta">版权声明: </span><span class="post-copyright-info">本博客所有文章除特别声明外，均采用 <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/" target="_blank">CC BY-NC-SA 4.0</a> 许可协议。转载请注明来自 <a href="http://yzb317415.gitee.io/blog" target="_blank">梓琰苑</a>！</span></div></div><div class="tag_share"><div class="post-meta__tag-list"><a class="post-meta__tags" href="/blog/tags/Spring/">Spring</a></div><div class="post_share"><div class="social-share" data-image="" data-sites="facebook,twitter,wechat,weibo,qq"></div><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/social-share.js/dist/css/share.min.css" media="print" onload="this.media='all'"><script src="https://cdn.jsdelivr.net/gh/overtrue/share.js@master/dist/js/social-share.min.js" defer></script></div></div><nav class="pagination-post" id="pagination"><div class="prev-post pull-left"><a href="/blog/2022/06/22/%E8%BD%AF%E4%BB%B6%E9%9C%80%E6%B1%82%E7%9A%84%E6%9C%AC%E8%B4%A8/"><img class="prev-cover" src="" onerror="onerror=null;src='/blog/img/404.jpg'" alt="cover of previous post"><div class="pagination-info"><div class="label">上一篇</div><div class="prev_info">软件需求的本质</div></div></a></div><div class="next-post pull-right"><a href="/blog/2022/06/22/Spring%E7%9A%84%E4%BA%8B%E5%8A%A1/"><img class="next-cover" src="" onerror="onerror=null;src='/blog/img/404.jpg'" alt="cover of next post"><div class="pagination-info"><div class="label">下一篇</div><div class="next_info">Spring 的事务</div></div></a></div></nav><div class="relatedPosts"><div class="headline"><i class="fas fa-thumbs-up fa-fw"></i><span>相关推荐</span></div><div class="relatedPosts-list"><div><a href="/blog/2022/06/22/SpringAOP/" title="SpringAOP"><img class="cover" src="" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2022-06-22</div><div class="title">SpringAOP</div></div></a></div><div><a href="/blog/2022/06/22/Spring%E7%9A%84%E4%BA%8B%E5%8A%A1/" title="Spring 的事务"><img class="cover" src="" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2022-06-22</div><div class="title">Spring 的事务</div></div></a></div><div><a href="/blog/2022/06/22/Spring%E7%9A%84%E7%BC%93%E5%AD%98%E6%9C%BA%E5%88%B6/" title="Spring的缓存机制"><img class="cover" src="" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2022-06-22</div><div class="title">Spring的缓存机制</div></div></a></div><div><a href="/blog/2022/06/22/%E6%B7%B1%E5%85%A5%E4%BD%BF%E7%94%A8%20Spring/" title="深入使用 Spring"><img class="cover" src="" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2022-06-22</div><div class="title">深入使用 Spring</div></div></a></div></div></div></div><div class="aside-content" id="aside-content"><div class="card-widget card-info"><div class="is-center"><div class="avatar-img"><img src="https://i.loli.net/2021/02/24/5O1day2nriDzjSu.png" onerror="this.onerror=null;this.src='/blog/img/friend_404.gif'" alt="avatar"/></div><div class="author-info__name">Milk Yang</div><div class="author-info__description">不积跬步无以至千里，不积小流无以成江海</div></div><div class="card-info-data site-data is-center"><a href="/blog/archives/"><div class="headline">文章</div><div class="length-num">8</div></a><a href="/blog/tags/"><div class="headline">标签</div><div class="length-num">2</div></a><a href="/blog/categories/"><div class="headline">分类</div><div class="length-num">1</div></a></div><a id="card-info-btn" target="_blank" rel="noopener" href="https://github.com/xxxxxx"><i class="fab fa-github"></i><span>Follow Me</span></a></div><div class="card-widget card-announcement"><div class="item-headline"><i class="fas fa-bullhorn fa-shake"></i><span>公告</span></div><div class="announcement_content">This is my Blog</div></div><div class="sticky_layout"><div class="card-widget" id="card-toc"><div class="item-headline"><i class="fas fa-stream"></i><span>目录</span><span class="toc-percentage"></span></div><div class="toc-content"><ol class="toc"><li class="toc-item toc-level-1"><a class="toc-link" href="#Spring%E5%85%A5%E9%97%A8"><span class="toc-number">1.</span> <span class="toc-text">Spring入门</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E4%BD%BF%E7%94%A8Spring%E5%AE%B9%E5%99%A8"><span class="toc-number">1.1.</span> <span class="toc-text">使用Spring容器</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#Spring%E5%AE%B9%E5%99%A8"><span class="toc-number">1.1.1.</span> <span class="toc-text">Spring容器</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E4%BD%BF%E7%94%A8ApplicationContext"><span class="toc-number">1.1.2.</span> <span class="toc-text">使用ApplicationContext</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#ApplicationContext%E7%9A%84%E4%BA%8B%E4%BB%B6%E6%94%AF%E6%8C%81"><span class="toc-number">1.1.3.</span> <span class="toc-text">ApplicationContext的事件支持</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E8%AE%A9Bean%E8%8E%B7%E5%8F%96Spring%E5%AE%B9%E5%99%A8"><span class="toc-number">1.1.4.</span> <span class="toc-text">让Bean获取Spring容器</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%AE%B9%E5%99%A8%E4%B8%AD%E7%9A%84Bean"><span class="toc-number">1.2.</span> <span class="toc-text">容器中的Bean</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#Bean%E7%9A%84%E5%9F%BA%E6%9C%AC%E5%AE%9A%E4%B9%89%E5%92%8CBean%E5%88%AB%E5%90%8D"><span class="toc-number">1.2.1.</span> <span class="toc-text">Bean的基本定义和Bean别名</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%AE%B9%E5%99%A8%E4%B8%ADBean%E7%9A%84%E4%BD%9C%E7%94%A8%E5%9F%9F"><span class="toc-number">1.2.2.</span> <span class="toc-text">容器中Bean的作用域</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E9%85%8D%E7%BD%AE%E4%BE%9D%E8%B5%96"><span class="toc-number">1.2.3.</span> <span class="toc-text">配置依赖</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E8%AE%BE%E7%BD%AE%E6%99%AE%E9%80%9A%E5%B1%9E%E6%80%A7%E5%80%BC"><span class="toc-number">1.2.4.</span> <span class="toc-text">设置普通属性值</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E9%85%8D%E7%BD%AE%E5%90%88%E4%BD%9C%E8%80%85Bean"><span class="toc-number">1.2.5.</span> <span class="toc-text">配置合作者Bean</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E4%BD%BF%E7%94%A8%E8%87%AA%E5%8A%A8%E8%A3%85%E9%85%8D%E6%B3%A8%E5%85%A5%E5%90%88%E4%BD%9C%E8%80%85Bean"><span class="toc-number">1.2.6.</span> <span class="toc-text">使用自动装配注入合作者Bean</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%B3%A8%E5%85%A5%E5%B5%8C%E5%A5%97Bean"><span class="toc-number">1.2.7.</span> <span class="toc-text">注入嵌套Bean</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%B3%A8%E5%85%A5%E9%9B%86%E5%90%88%E5%80%BC"><span class="toc-number">1.2.8.</span> <span class="toc-text">注入集合值</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E7%BB%84%E5%90%88%E5%B1%9E%E6%80%A7"><span class="toc-number">1.2.9.</span> <span class="toc-text">组合属性</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Spring%E6%8F%90%E4%BE%9B%E7%9A%84Java%E9%85%8D%E7%BD%AE%E7%AE%A1%E7%90%86"><span class="toc-number">1.3.</span> <span class="toc-text">Spring提供的Java配置管理</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%88%9B%E5%BB%BABean%E7%9A%843%E7%A7%8D%E6%96%B9%E5%BC%8F"><span class="toc-number">1.4.</span> <span class="toc-text">创建Bean的3种方式</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E4%BD%BF%E7%94%A8%E6%9E%84%E9%80%A0%E5%99%A8%E5%88%9B%E5%BB%BABean%E5%AE%9E%E4%BE%8B"><span class="toc-number">1.4.1.</span> <span class="toc-text">使用构造器创建Bean实例</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E4%BD%BF%E7%94%A8%E9%9D%99%E6%80%81%E5%B7%A5%E5%8E%82%E5%88%9B%E5%BB%BABean"><span class="toc-number">1.4.2.</span> <span class="toc-text">使用静态工厂创建Bean</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E8%B0%83%E7%94%A8%E5%AE%9E%E4%BE%8B%E5%B7%A5%E5%8E%82%E6%96%B9%E6%B3%95%E5%88%9B%E5%BB%BABean"><span class="toc-number">1.4.3.</span> <span class="toc-text">调用实例工厂方法创建Bean</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%B7%B1%E5%85%A5%E7%90%86%E8%A7%A3%E5%AE%B9%E5%99%A8%E4%B8%AD%E7%9A%84Bean"><span class="toc-number">1.5.</span> <span class="toc-text">深入理解容器中的Bean</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%8A%BD%E8%B1%A1Bean%E4%B8%8E%E5%AD%90Bean"><span class="toc-number">1.5.1.</span> <span class="toc-text">抽象Bean与子Bean</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%AE%B9%E5%99%A8%E4%B8%AD%E7%9A%84%E5%B7%A5%E5%8E%82Bean"><span class="toc-number">1.5.2.</span> <span class="toc-text">容器中的工厂Bean</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E8%8E%B7%E5%BE%97Bean%E8%87%AA%E8%BA%AB%E7%9A%84id"><span class="toc-number">1.5.3.</span> <span class="toc-text">获得Bean自身的id</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%BC%BA%E5%88%B6%E5%88%9D%E5%A7%8B%E5%8C%96Bean"><span class="toc-number">1.5.4.</span> <span class="toc-text">强制初始化Bean</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E4%BE%9D%E8%B5%96%E5%85%B3%E7%B3%BB%E6%B3%A8%E5%85%A5%E4%B9%8B%E5%90%8E%E7%9A%84%E8%A1%8C%E4%B8%BA"><span class="toc-number">1.5.5.</span> <span class="toc-text">依赖关系注入之后的行为</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#Bean%E9%94%80%E6%AF%81%E4%B9%8B%E5%89%8D%E7%9A%84%E8%A1%8C%E4%B8%BA"><span class="toc-number">1.5.6.</span> <span class="toc-text">Bean销毁之前的行为</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%8D%8F%E8%B0%83%E4%BD%9C%E7%94%A8%E5%9F%9F%E4%B8%8D%E5%90%8C%E7%9A%84%E6%AD%A5%E7%9A%84Bean"><span class="toc-number">1.5.7.</span> <span class="toc-text">协调作用域不同的步的Bean</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E9%AB%98%E7%BA%A7%E4%BE%9D%E8%B5%96%E5%85%B3%E7%B3%BB%E9%85%8D%E7%BD%AE"><span class="toc-number">1.6.</span> <span class="toc-text">高级依赖关系配置</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E8%8E%B7%E5%8F%96%E5%85%B6%E4%BB%96Bean%E7%9A%84%E5%B1%9E%E6%80%A7%E5%80%BC"><span class="toc-number">1.6.1.</span> <span class="toc-text">获取其他Bean的属性值</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E8%8E%B7%E5%8F%96Field%E5%80%BC"><span class="toc-number">1.6.2.</span> <span class="toc-text">获取Field值</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E8%8E%B7%E5%8F%96%E6%96%B9%E6%B3%95%E8%BF%94%E5%9B%9E%E5%80%BC"><span class="toc-number">1.6.3.</span> <span class="toc-text">获取方法返回值</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%9F%BA%E4%BA%8EXML-Schema-%E7%9A%84%E7%AE%80%E5%8C%96%E9%85%8D%E7%BD%AE%E6%96%B9%E5%BC%8F"><span class="toc-number">1.7.</span> <span class="toc-text">基于XML Schema 的简化配置方式</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E4%BD%BF%E7%94%A8-p-%E5%91%BD%E5%90%8D%E7%A9%BA%E9%97%B4%E7%AE%80%E5%8C%96%E9%85%8D%E7%BD%AE-%E7%AE%80%E5%8C%96%E8%AE%BE%E5%80%BC%E6%B3%A8%E5%85%A5"><span class="toc-number">1.7.1.</span> <span class="toc-text">使用 p:命名空间简化配置(简化设值注入)</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E4%BD%BF%E7%94%A8c-%E5%91%BD%E5%90%8D%E6%8E%A7%E4%BB%B6%E7%AE%80%E5%8C%96%E9%85%8D%E7%BD%AE%EF%BC%88%E7%AE%80%E5%8C%96%E6%9E%84%E9%80%A0%E6%B3%A8%E5%85%A5%EF%BC%89"><span class="toc-number">1.7.2.</span> <span class="toc-text">使用c:命名控件简化配置（简化构造注入）</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E4%BD%BF%E7%94%A8-util-%E5%91%BD%E5%90%8D%E7%A9%BA%E9%97%B4%E7%AE%80%E5%8C%96%E9%85%8D%E7%BD%AE"><span class="toc-number">1.7.3.</span> <span class="toc-text">使用 util:命名空间简化配置</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#SpEL-%E8%AF%AD%E6%B3%95%E8%AF%A6%E8%BF%B0"><span class="toc-number">1.7.4.</span> <span class="toc-text">SpEL 语法详述</span></a></li></ol></li></ol></li></ol></div></div><div class="card-widget card-recent-post"><div class="item-headline"><i class="fas fa-history"></i><span>最新文章</span></div><div class="aside-list"><div class="aside-list-item"><a class="thumbnail" href="/blog/2022/06/22/SpringAOP/" title="SpringAOP"><img src="" onerror="this.onerror=null;this.src='/blog/img/404.jpg'" alt="SpringAOP"/></a><div class="content"><a class="title" href="/blog/2022/06/22/SpringAOP/" title="SpringAOP">SpringAOP</a><time datetime="2022-06-22T10:06:45.841Z" title="发表于 2022-06-22 18:06:45">2022-06-22</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/blog/2022/06/22/%E9%9C%80%E6%B1%82%E5%BC%80%E5%8F%91/" title="需求开发"><img src="" onerror="this.onerror=null;this.src='/blog/img/404.jpg'" alt="需求开发"/></a><div class="content"><a class="title" href="/blog/2022/06/22/%E9%9C%80%E6%B1%82%E5%BC%80%E5%8F%91/" title="需求开发">需求开发</a><time datetime="2022-06-22T10:06:45.837Z" title="发表于 2022-06-22 18:06:45">2022-06-22</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/blog/2022/06/22/%E6%B7%B1%E5%85%A5%E4%BD%BF%E7%94%A8%20Spring/" title="深入使用 Spring"><img src="" onerror="this.onerror=null;this.src='/blog/img/404.jpg'" alt="深入使用 Spring"/></a><div class="content"><a class="title" href="/blog/2022/06/22/%E6%B7%B1%E5%85%A5%E4%BD%BF%E7%94%A8%20Spring/" title="深入使用 Spring">深入使用 Spring</a><time datetime="2022-06-22T10:06:45.833Z" title="发表于 2022-06-22 18:06:45">2022-06-22</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/blog/2022/06/22/%E8%BD%AF%E4%BB%B6%E9%9C%80%E6%B1%82%E7%9A%84%E6%9C%AC%E8%B4%A8/" title="软件需求的本质"><img src="" onerror="this.onerror=null;this.src='/blog/img/404.jpg'" alt="软件需求的本质"/></a><div class="content"><a class="title" href="/blog/2022/06/22/%E8%BD%AF%E4%BB%B6%E9%9C%80%E6%B1%82%E7%9A%84%E6%9C%AC%E8%B4%A8/" title="软件需求的本质">软件需求的本质</a><time datetime="2022-06-22T10:06:45.828Z" title="发表于 2022-06-22 18:06:45">2022-06-22</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/blog/2022/06/22/Spring%E5%85%A5%E9%97%A8/" title="Spring入门"><img src="" onerror="this.onerror=null;this.src='/blog/img/404.jpg'" alt="Spring入门"/></a><div class="content"><a class="title" href="/blog/2022/06/22/Spring%E5%85%A5%E9%97%A8/" title="Spring入门">Spring入门</a><time datetime="2022-06-22T10:06:45.824Z" title="发表于 2022-06-22 18:06:45">2022-06-22</time></div></div></div></div></div></div></main><footer id="footer"><div id="footer-wrap"><div class="copyright">&copy;2020 - 2022 By Milk Yang</div><div class="framework-info"><span>框架 </span><a target="_blank" rel="noopener" href="https://hexo.io">Hexo</a><span class="footer-separator">|</span><span>主题 </span><a target="_blank" rel="noopener" href="https://github.com/jerryc127/hexo-theme-butterfly">Butterfly</a></div></div></footer></div><div id="rightside"><div id="rightside-config-hide"><button id="readmode" type="button" title="阅读模式"><i class="fas fa-book-open"></i></button><button id="darkmode" type="button" title="浅色和深色模式转换"><i class="fas fa-adjust"></i></button><button id="hide-aside-btn" type="button" title="单栏和双栏切换"><i class="fas fa-arrows-alt-h"></i></button></div><div id="rightside-config-show"><button id="rightside_config" type="button" title="设置"><i class="fas fa-cog fa-spin"></i></button><button class="close" id="mobile-toc-button" type="button" title="目录"><i class="fas fa-list-ul"></i></button><button id="go-up" type="button" title="回到顶部"><i class="fas fa-arrow-up"></i></button></div></div><div><script src="/blog/js/utils.js"></script><script src="/blog/js/main.js"></script><script src="https://cdn.jsdelivr.net/npm/@fancyapps/ui/dist/fancybox.umd.js"></script><div class="js-pjax"></div><script async data-pjax src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script></div></body></html>